package com.longge.common.configuration;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import org.apache.commons.lang3.StringUtils;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.ZooKeeper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.longge.common.util.ZkUtils;

import lombok.Getter;
import lombok.Setter;

@Configuration
@ConditionalOnProperty(prefix = "zookeeper", name = "enabled", havingValue = "true", matchIfMissing = true)
@ConditionalOnClass(value= {CuratorFramework.class, ZooKeeper.class})
public class ZkCuratorAutoConfiguration {
	@Autowired
	private CuratorConfig config;

	@Bean
	public CuratorFramework client() {
		// ExponentialBackoffRetry、RetryNTimes、RetryOneTimes、RetryUntilElapsed
		RetryPolicy retryPolicy = new ExponentialBackoffRetry(config.getBaseSleepTimeMs(), config.getMaxRetries());
		CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
				.connectString(config.getServer())
				.retryPolicy(retryPolicy);
		if(null != config.getSessionTimeoutMs()) {
			builder.sessionTimeoutMs(config.getSessionTimeoutMs());
		}
		if(null != config.getConnectionTimeoutMs()) {
			builder.connectionTimeoutMs(config.getConnectionTimeoutMs());
		}
		if(StringUtils.isNotBlank(config.getNamespace())) {
			builder.namespace(config.getNamespace());
		}
		CuratorFramework client = builder.build();
		client.start();
		
		ZkUtils.setClient(client);
		return client;
	}

	@Getter
	@Setter
	@Valid
	@Configuration
	@ConfigurationProperties(prefix = "zookeeper")
	public static class CuratorConfig {
		private Boolean enabled = Boolean.TRUE;
		
		@NotNull
		private String server;
		/**
		 * base path
		 */
		private String namespace;
		/**
		 * if null, value is: CuratorFrameworkFactory.DEFAULT_SESSION_TIMEOUT_MS = Integer.getInteger("curator-default-session-timeout", 60 * 1000);
		 */
		private Integer sessionTimeoutMs;
		/**
		 * if null, value is: CuratorFrameworkFactory.DEFAULT_CONNECTION_TIMEOUT_MS = Integer.getInteger("curator-default-connection-timeout", 15 * 1000);
		 */
		private Integer connectionTimeoutMs;
		/**
		 * wait time
		 */
		private Integer baseSleepTimeMs = 2000;
		/**
		 * max retry count
		 */
		private Integer maxRetries = 3;
	}
}
